(define-module (mach task)
  #:export (task-self task-get-special-port task-get-bootstrap-port)
  #:use-module (mach ffi)
  #:use-module (mach types))

(define-ffi ("mach_task_self" %mach-task-self)
  (ffi:ipc-space identity))

;; TODO: is this a new send right?
;; That is, do we need to deallocate this eventually?
(define (task-self)
  "Return a send right associated with the task_self port"
  (%mach-task-self))

(define-ffi ("task_get_special_port" %task-get-special-port)
  (err identity) ; XXX ???
  (task ffi:task %unwrap-task)
  (what special-port-type %unwrap-special-port-type)
  (port-box '* identity)) ;; <-- IIUC, the port will be written there.

;; XXX what is WHAT?
;; XXX what is a ‘send write’?
(define* (task-get-special-port what #:optional (task (task-self)))
  "Return a send write to the indicated special port."
  ;; The initial value of the foreign box does not matter.
  (let* ((port-box (make-c-struct '* %null-pointer))
         (return-code (%task-get-special-port task what port-box)))
    (select-error return-code
                  (%wrap-mach-port (dereference-pointer port-box)))))

(define* (task-get-bootstrap-port #:optional (task (task-self)))
  "Return a send write to the bootstrap port."
  ;; XXX where is :task-bootstrap-port defined?
  (task-get-special-port :task-bootstrap-port task))

